/*
 * Alloy Analyzer
 * Copyright (c) 2002 Massachusetts Institute of Technology
 *
 * The Alloy Analyzer is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * The Alloy Analyzer is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with the Alloy Analyzer; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

package alloy.util;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 * A wrapper around an {@link Iterator} that turns it into a
 * {@link ResettableIterator}, by caching the values yielded
 * by the original iterator, and yielding them again after
 * a {@link #rewind} as necessary.
 */
public class CachingIterator implements ResettableIterator {
    /** The original iterator */
    private Iterator _iterator;

    /** Sequence of values yielded by the {@link #_iterator} so far. */
    private List _values = new ArrayList();

    /**
     * Index of the next value from {@link #_values} to yield.  If equal
     * to <code>_values.size()</code>, next value will be taken from
     * the original {@link #_iterator}.
     */
    private int _nextValIndex;

    /** Construct a caching wrapper around the given iterator. */
    public CachingIterator(Iterator iterator_) {
	_iterator = iterator_;
    }

    public boolean hasNext() { return _nextValIndex < _values.size() || _iterator.hasNext(); }

    public Object next() {
	if (_nextValIndex < _values.size())
	    return _values.get(_nextValIndex++);
	Object nextVal = _iterator.next();
	_values.add(nextVal);
	_nextValIndex++;
	return nextVal;
    }

    public void rewind() { _nextValIndex = 0; }

    public void remove() throws UnsupportedOperationException
    { throw new UnsupportedOperationException("CachingIterator.remove()"); }
}
